#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "Comm.h"
#include "constant.h"

void setnonblock(int socks)
{
	int opts;
	opts = fcntl(socks, F_GETFL);
	if(opts < 0)
	{
		perror("fcntl(socks, F_GETFL)");
		exit(1);
	}
	opts = opts | O_NONBLOCK;
	if(fcntl(socks, F_SETFL, opts) < 0)
	{
		perror("fcntl(socks, F_SETFL, opts)");
		exit(1);
	}
}

int main(int argc, char *argv[])
{
	printf("Service run at Port: %d\n", SRV_PORT);
	printf("Usage: %s\n", USAGE);
	int i, listenfd, connfd, sockfd, epfd, nfds;
	int on = 1;
	ssize_t n;
	char line[MAXLINE];
	socklen_t clilen;
	struct epoll_event ev, events[20];
	struct sockaddr_in clientaddr;
	struct sockaddr_in serveraddr;
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	setnonblock(listenfd);
	if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) == -1)
	{
		perror("reuse error");
		exit(1);
	}
	bzero(&serveraddr, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(SRV_PORT);
	char *local_addr = "0.0.0.0";
	inet_aton(local_addr, &(serveraddr.sin_addr));
	bind(listenfd,(struct sockaddr *)&serveraddr, sizeof(serveraddr));
	listen(listenfd, LISTENQ);
	ev.data.fd = listenfd;
	ev.events = EPOLLIN;
	epfd = epoll_create(256);
	epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
	int maxi = 0;
	for( ; ; )
	{
		nfds = epoll_wait(epfd, events, 20, 500);
		for(i = 0; i < nfds; i++)
		{
			if(events[i].data.fd == listenfd)
			{
				connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clilen);
				if(connfd < 0)
				{
					perror("connfd error");
					return 0;
				}
				setnonblock(connfd);
				char *str = inet_ntoa(clientaddr.sin_addr);
				printf("accapt a connection from %s\n", str);
				ev.data.fd = connfd;
//				ev.events = EPOLLIN|EPOLLET;
				ev.events = EPOLLIN;
				epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
			}
			else if(events[i].events & EPOLLIN)
			{
				printf("I am in EPOLLIN\n");
				if((sockfd = events[i].data.fd) < 0)
				{
					puts("continue\n");
					continue;
				}
				puts("continue ok!\n");
				if((n = read(sockfd, line, MAXLINE)) < 0)
				{
					if(errno == ECONNRESET)
					{
						puts("3");
						perror("ECONNRESET");
						//close(sockfd);
						//events[i].data.fd = -1;
					}
					else
					{
						printf("read error!\n");
					}
				}
				else if(n == 0)
				{
					//close(sockfd);
					puts("23");
					//events[i].data.fd = -1;
				}
				else
				{
					puts("123");
				}
				line[n] = '\0';
				printf("read: %d : %s \n", n, line);
				ev.data.fd = sockfd;
				//ev.events = EPOLLOUT | EPOLLET;
				ev.events = EPOLLOUT;
				puts("Set ok!");
				epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
			}
			else if(events[i].events & EPOLLOUT)
			{
				printf("I am in EPOLLOUT\n");
				sockfd = events[i].data.fd;
				char out[MAXLINE];
				memset(out, '\0', sizeof(out));
				sprintf(out, "%s", "welcome to here!");
				puts(out);
				write(sockfd, out, sizeof(out));
				ev.data.fd = sockfd;
				ev.events = EPOLLIN | EPOLLET;
				epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
			}
			else if(events[i].events & (EPOLLHUP | EPOLLERR))
			{
				if(epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &ev) < 0)
				{
					perror("epoll del ctl error!");
					close(sockfd);
				}
			}
			else
				fprintf(stderr, "%d %d\n", sockfd, events[i].events);
		}
//		char *now;
//		now = GetFormatTime();
//		printf("One times, Now is %s ", now);
	}
	return 0;
}

